﻿using JNPF.Basics.Models;
using JNPF.Utils;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Transactions;

namespace JNPF.Basics.Logic
{
    /// <summary>
    /// 邮件收发
    /// 版 本：V3.0.0
    /// 版 权：引迈信息技术有限公司（https://www.jnpfsoft.com）
    /// 作 者：JNPF开发平台组
    /// 日 期：2017.11.28 
    /// </summary>
    public class EmailBll
    {
        private EmailIService service = new EmailService();

        /// <summary>
        /// 列表（收件箱）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        public async Task<PageResult<EmailReceiveEntity>> GetReceiveList(PageInput input)
        {
            try
            {
                var userId = UserProvider.Instance.Get().UserId;
                return await service.GetReceiveList(userId, input);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }

        /// <summary>
        /// 列表（未读邮件）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        public async Task<PageResult<EmailReceiveEntity>> GetUnreadList(PageInput input)
        {
            try
            {
                var userId = UserProvider.Instance.Get().UserId;
                return await service.GetUnreadList(userId, input);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 列表（星标件）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        public async Task<PageResult<EmailReceiveEntity>> GetStarredList(PageInput input)
        {
            try
            {
                var userId = UserProvider.Instance.Get().UserId;
                return await service.GetStarredList(userId, input);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 列表（草稿箱）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        public async Task<PageResult<EmailSendEntity>> GetDraftList(PageInput input)
        {
            try
            {
                var userId = UserProvider.Instance.Get().UserId;
                return await service.GetDraftList(userId, input);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 列表（已发送）
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        public async Task<PageResult<EmailSendEntity>> GetSentList(PageInput input)
        {
            try
            {
                var userId = UserProvider.Instance.Get().UserId;
                return await service.GetSentList(userId, input);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 信息（配置）
        /// </summary>
        /// <param name="userId">用户主键</param>
        /// <returns></returns>
        public async Task<EmailConfigEntity> GetConfigInfo(string userId)
        {
            try
            {
                return await service.GetConfigInfo(userId);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 信息（收件/发件）
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        public async Task<object> GetInfo(string id)
        {
            try
            {
                var entity = await service.GetInfo(id);
                if (entity is EmailReceiveEntity)
                {
                    //更新已读
                    EmailReceiveEntity emailReceiveEntity = entity.MapTo<EmailReceiveEntity>();
                    emailReceiveEntity.Read = 1;
                    emailReceiveEntity.LastModifyTime = DateTime.Now;
                    emailReceiveEntity.LastModifyUserId = UserProvider.Instance.Get().UserId;
                    await service.Update(emailReceiveEntity);
                }
                return entity;
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 删除邮件（发、收）
        /// </summary>
        /// <param name="id">主键值</param>
        public async Task Delete(string id)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    var entity = await this.GetInfo(id);
                    if (entity is EmailReceiveEntity)
                    {
                        //删除邮件
                        var userId = UserProvider.Instance.Get().UserId;
                        var mailConfig = await this.GetConfigInfo(userId);
                        var mailReceiveEntity = entity.MapTo<EmailReceiveEntity>();
                        MailHelper.Delete(new MailAccount { Account = mailConfig.Account, Password = mailConfig.Password, POP3Host = mailConfig.POP3Host, POP3Port = mailConfig.POP3Port.ToInt() }, mailReceiveEntity.MID);
                    }
                    //删除数据
                    await service.Delete(entity);
                    //提交事物
                    scope.Complete();
                }
            }
            catch (TransactionAbortedException ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 存草稿
        /// </summary>
        /// <param name="entity">实体对象</param>
        public async Task SaveDraft(EmailSendEntity entity)
        {
            try
            {
                entity.State = -1;
                if (!string.IsNullOrEmpty(entity.Id))
                {
                    entity.LastModifyTime = DateTime.Now;
                    entity.LastModifyUserId = UserProvider.Instance.Get().UserId;
                    await service.Update(entity);
                }
                else
                {
                    entity.Id = CommonHelper.Guid;
                    entity.CreatorTime = DateTime.Now;
                    entity.CreatorUserId = UserProvider.Instance.Get().UserId;
                    await service.Create(entity);
                }
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 发邮件
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <param name="userId">用户主键</param>
        /// <param name="mailConfig">邮件配置</param>
        public async Task SaveSent(EmailSendEntity entity, string userId, EmailConfigEntity mailConfig)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    //写入数据
                    if (!string.IsNullOrEmpty(entity.Id))
                    {
                        entity.CreatorTime = DateTime.Now;
                        entity.State = 1;
                        await service.Update(entity);
                    }
                    else
                    {
                        entity.Id = CommonHelper.Guid;
                        entity.CreatorTime = DateTime.Now;
                        entity.CreatorUserId = UserProvider.Instance.Get().UserId;
                        entity.Sender = mailConfig.Account;
                        entity.State = 1;
                        await service.Create(entity);
                    }
                    //拷贝文件,注意：从临时文件夹拷贝到邮件文件夹
                    var attachmentList = JsonHelper.ToList<MailFile>(entity.Attachment);
                    var temporaryFile = ConfigurationKey.TemporaryFilePath;
                    var mailFilePath = ConfigurationKey.EmailFilePath;
                    foreach (MailFile mailFile in attachmentList)
                    {
                        FileHelper.MoveFile(temporaryFile + mailFile.FileId, mailFilePath + mailFile.FileId);
                    }
                    //发送邮件
                    var mailModel = new MailModel();
                    mailModel.To = entity.To;
                    mailModel.CC = entity.CC;
                    mailModel.Bcc = entity.BCC;
                    mailModel.Subject = entity.Subject;
                    mailModel.BodyText = WebHelper.HtmlDecode(entity.BodyText);
                    mailModel.Attachment = attachmentList;
                    MailHelper.Send(new MailAccount { AccountName = mailConfig.SenderName, Account = mailConfig.Account, Password = mailConfig.Password, SMTPHost = mailConfig.SMTPHost, SMTPPort = mailConfig.SMTPPort.ToInt() }, mailModel);
                    //提交事物
                    scope.Complete();
                }
            }
            catch (TransactionAbortedException ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 收邮件（从邮件服务器下载邮件回来）
        /// </summary>
        /// <param name="userId">用户主键</param>
        /// <param name="mailConfig">邮件配置</param>
        /// <returns></returns>
        public async Task<int> Receive(string userId, EmailConfigEntity mailConfig)
        {
            try
            {
                List<EmailReceiveEntity> entitys = new List<EmailReceiveEntity>();
                var receiveCount = await service.GetReceiveCount(mailConfig.Account);//已收邮件数
                var mailList = MailHelper.Get(new MailAccount { Account = mailConfig.Account, Password = mailConfig.Password, POP3Host = mailConfig.POP3Host, POP3Port = mailConfig.POP3Port.ToInt() }, receiveCount);
                foreach (MailModel mailModel in mailList)
                {
                    entitys.Add(new EmailReceiveEntity
                    {
                        Id = CommonHelper.Guid,
                        MAccount = mailConfig.Account,
                        MID = mailModel.UID,
                        Sender = mailModel.To,
                        SenderName = mailModel.ToName,
                        Subject = mailModel.Subject,
                        BodyText = WebHelper.HtmlEncode(mailModel.BodyText),
                        Attachment = mailModel.Attachment.ToJson(),
                        Date = mailModel.Date,
                        Read = 0,
                        CreatorTime = DateTime.Now,
                        CreatorUserId = userId
                    });
                }
                await service.Create(entitys);
                return entitys.Count;
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 收邮件设置 已读/未读
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="isRead">0-未读、1-已读</param>
        /// <returns></returns>
        public async Task<int> ReceiveRead(string id, int isRead)
        {
            try
            {
                var entity = (await this.GetInfo(id)).MapTo<EmailReceiveEntity>();
                entity.Read = isRead;
                return await service.Update(entity);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 收邮件 星标邮件/取消星标
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="isStarred">1-星标邮件/0-取消星标</param>
        /// <returns></returns>
        public async Task<int> ReceiveStarred(string id, int isStarred)
        {
            try
            {
                var entity = (await this.GetInfo(id)).MapTo<EmailReceiveEntity>();
                entity.Starred = isStarred;
                return await service.Update(entity);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
        /// <summary>
        /// 保存邮箱配置
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <returns></returns>
        public async Task<int> SaveConfig(EmailConfigEntity entity)
        {
            try
            {
                return await service.SaveConfig(entity);
            }
            catch (Exception ex)
            {
                throw ExceptionEx.Throw(ex);
            }
        }
    }
}
